From f3fc4cd30470f504587c7d89f9c83a6cb544b69f Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 8 Dec 2005 15:13:38 +0100 Subject: [PATCH] Improve VMX guest TSC accuracy when guests are competing for the same physical CPU. Signed-off-by: Eddie Dong --- xen/arch/x86/vmx.c | 2 +- xen/arch/x86/vmx_intercept.c | 1 - xen/arch/x86/vmx_io.c | 34 +++++++++++++++++++++++----------- xen/arch/x86/vmx_vmcs.c | 6 +++++- xen/include/asm-x86/vmx_vpit.h | 2 +- 5 files changed, 30 insertions(+), 15 deletions(-) diff --git a/xen/arch/x86/vmx.c b/xen/arch/x86/vmx.c index b4878317a0..e8e1c9f1e0 100644 --- a/xen/arch/x86/vmx.c +++ b/xen/arch/x86/vmx.c @@ -108,7 +108,7 @@ void vmx_relinquish_resources(struct vcpu *v) destroy_vmcs(&v->arch.arch_vmx); free_monitor_pagetable(v); vpit = &v->domain->arch.vmx_platform.vmx_pit; - if ( vpit->ticking && active_ac_timer(&(vpit->pit_timer)) ) + if ( active_ac_timer(&(vpit->pit_timer)) ) rem_ac_timer(&vpit->pit_timer); if ( active_ac_timer(&v->arch.arch_vmx.hlt_timer) ) { rem_ac_timer(&v->arch.arch_vmx.hlt_timer); diff --git a/xen/arch/x86/vmx_intercept.c b/xen/arch/x86/vmx_intercept.c index 67029c2c95..69aeb4f325 100644 --- a/xen/arch/x86/vmx_intercept.c +++ b/xen/arch/x86/vmx_intercept.c @@ -387,7 +387,6 @@ void vmx_hooks_assist(struct vcpu *v) } else { init_ac_timer(&vpit->pit_timer, pit_timer_fn, v, v->processor); - vpit->ticking = 1; } /* init count for this channel */ diff --git a/xen/arch/x86/vmx_io.c b/xen/arch/x86/vmx_io.c index 5557e03474..5caa59bc04 100644 --- a/xen/arch/x86/vmx_io.c +++ b/xen/arch/x86/vmx_io.c @@ -793,29 +793,39 @@ static __inline__ int find_highest_irq(u32 *pintr) return __fls(pintr[0]); } +void set_tsc_shift(struct vcpu *v,struct vmx_virpit *vpit) +{ + u64 drift; + + if ( vpit->first_injected ) + drift = vpit->period_cycles * vpit->pending_intr_nr; + else + drift = 0; + drift = v->arch.arch_vmx.tsc_offset - drift; + __vmwrite(TSC_OFFSET, drift); + +#if defined (__i386__) + __vmwrite(TSC_OFFSET_HIGH, (drift >> 32)); +#endif +} + #define BSP_CPU(v) (!(v->vcpu_id)) static inline void interrupt_post_injection(struct vcpu * v, int vector, int type) { struct vmx_virpit *vpit = &(v->domain->arch.vmx_platform.vmx_pit); - u64 drift; if ( is_pit_irq(v, vector, type) ) { if ( !vpit->first_injected ) { - vpit->first_injected = 1; vpit->pending_intr_nr = 0; + vpit->scheduled = NOW() + vpit->period; + set_ac_timer(&vpit->pit_timer, vpit->scheduled); + vpit->first_injected = 1; } else { vpit->pending_intr_nr--; } vpit->inject_point = NOW(); - drift = vpit->period_cycles * vpit->pending_intr_nr; - drift = v->arch.arch_vmx.tsc_offset - drift; - __vmwrite(TSC_OFFSET, drift); - -#if defined (__i386__) - __vmwrite(TSC_OFFSET_HIGH, (drift >> 32)); -#endif - + set_tsc_shift (v, vpit); } switch(type) @@ -982,8 +992,10 @@ void vmx_do_resume(struct vcpu *v) vmx_wait_io(); } /* pick up the elapsed PIT ticks and re-enable pit_timer */ - if ( vpit->ticking ) + if ( vpit->first_injected ) { pickup_deactive_ticks(vpit); + } + set_tsc_shift(v,vpit); /* We can't resume the guest if we're waiting on I/O */ ASSERT(!test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags)); diff --git a/xen/arch/x86/vmx_vmcs.c b/xen/arch/x86/vmx_vmcs.c index 04b5c6bc25..55d7741f2e 100644 --- a/xen/arch/x86/vmx_vmcs.c +++ b/xen/arch/x86/vmx_vmcs.c @@ -290,6 +290,7 @@ static void vmx_do_launch(struct vcpu *v) /* Update CR3, GDT, LDT, TR */ unsigned int error = 0; unsigned long cr0, cr4; + u64 host_tsc; if (v->vcpu_id == 0) vmx_setup_platform(v->domain); @@ -337,6 +338,10 @@ static void vmx_do_launch(struct vcpu *v) __vmwrite(HOST_RSP, (unsigned long)get_stack_bottom()); v->arch.schedule_tail = arch_vmx_do_resume; + /* init guest tsc to start from 0 */ + rdtscll(host_tsc); + v->arch.arch_vmx.tsc_offset = 0 - host_tsc; + set_tsc_shift (v, &v->domain->arch.vmx_platform.vmx_pit); } /* @@ -366,7 +371,6 @@ static inline int construct_init_vmcs_guest(cpu_user_regs_t *regs) error |= __vmwrite(PAGE_FAULT_ERROR_CODE_MATCH, 0); /* TSC */ - error |= __vmwrite(TSC_OFFSET, 0); error |= __vmwrite(CR3_TARGET_COUNT, 0); /* Guest Selectors */ diff --git a/xen/include/asm-x86/vmx_vpit.h b/xen/include/asm-x86/vmx_vpit.h index e5fb1bc368..e4e6d2b88c 100644 --- a/xen/include/asm-x86/vmx_vpit.h +++ b/xen/include/asm-x86/vmx_vpit.h @@ -27,7 +27,6 @@ struct vmx_virpit { unsigned int pending_intr_nr; /* the couner for pending timer interrupts */ u32 period; /* pit frequency in ns */ int first_injected; /* flag to prevent shadow window */ - int ticking; /* indicating it is ticking */ /* virtual PIT state for handle related I/O */ int read_state; @@ -51,5 +50,6 @@ static __inline__ s_time_t get_pit_scheduled( else return -1; } +extern void set_tsc_shift(struct vcpu *v,struct vmx_virpit *vpit); #endif /* _VMX_VIRPIT_H_ */ -- 2.30.2